类型提示 -Stubs

类型提示 -Stubs

官方文档:Stub Files

Pycharm 中队 Stubs 的支持:Stubs | PyCharm Documentation

参考文档:Python Stubs

模块骨架文件,后缀为 pyi,文件名要跟其描述的模块的文件名相同,用于声明其描述的模块的所有的变量,方法,类型,声明这些类型的存在,和他们的类型,其实主要是声明类型,

在 Pycharm 中拥有 stubs 文件的模块的方法或者类的左侧会有一个星号,用于在模块和其 stubs 文件之间相互跳转,

文档:Navigate between a stub and its implementation

其实你可以将类型信息直接写在模块文件中,而不是用一个专门的 pyi 文件村,但是 python2 和 python3 的方式不一样,因为 Python2.x 与 3​​.x 版本并不兼容

具体请看《类型提示.md

一般情况下 stubs 文件会与其修饰的模块处在同一目录,但是如果需要修饰的模块是下载的第三方模块,我们就需要新建同样的目录来存放 stubs 文件像这样。

请参考:Stubs | PyCharm Documentation | Create a stub file for the external implementation

其实我们不使用 stubs 文件,这样我们也可以直接 import 包中的模块,然后使用其变量和方法。但是创建了模块对应的 stubs 文件之后,我们就会以 stubs 文件中的信息为准,如果 stubs 文件中故意没有写其描述的模块中的某一个方法或者变量或者类,那么在 import 这个模块之后,我们将无法使用这个漏掉的方法或者变量或者类。

stubs 文件的功能:

简单实践

首先准备一下包结构

xyz 包和 xiashuo 包的 __init__.py 文件文件都是空的,重点看 str_function.py

name = "xiashuo"
age = 12


def str_greeting():
    print(f"Hello {name}")


def show_info(name, age):
    print(f"hello everyone , I am {name}, i am {age} years old")

str_function.pyi

def str_greeting() -> None: ...

# 在pyi中定义方法的类型信息跟直接在py中定义方法的类型信息在语法上的唯一的区别就是在pyi中方法体部分用 ... 代替
# 在这里声明方法和参数类型之后,使用这个方法的时候,就会有型提示
def show_info(name: str, age: int) -> None: ...

在 pyi 中定义方法的类型信息跟直接在 py 中定义方法的类型信息在语法上的唯一的区别就是在 pyi 中方法体部分用 ... 代替

.pyi 文件也就是 stubs 文件中声明变量的类型方法的参数和返回值类型之后,使用这个变量和方法的时候,就会有型提示。调用方法的时候传入的类型不对,也会有提示

测试代码如下:

from xyz.xiashuo.str_function import *

print(name)
print(age)

# 如果stubs中没有声明这个方法,在这里,解释器会报错,但是依然可以成功运行
str_greeting()

show_info("sdf", 12)
# 虽然类型跟stubs中的类型不匹配,但仅仅是警告,没有报错
show_info("dfdfa", "dfsd")

在 Pycharm 中,因为我们没有在 str_function.pyi 中声明 name 和 age 这两个变量,因此在导入后,解释器不知道这两个变量的含义,因此报错,但是不会阻止运行,而且在 str_function.py 中实际上是有这两个变量的,因此实际执行不会报错

.pyi 文件中,show_info 的第二个参数应该是 int,但是传入了 str,会有警告,但是不会阻止运行

输出:

xiashuo
12
Hello xiashuo
hello everyone , I am sdf, i am 12 years old
hello everyone , I am dfdfa, i am dfsd years old

从这里我们可以看到在 Python 中,类型信息的严格匹配,并不是程序执行的必要条件,即使类型不对,解释器也不会阻止代码的运行。从这个角度看类型信息确实是可有可无的

总结

如果你本身就偏向于编写带有类型信息的 python 代码,那么类型注解是你的首选,而不是 stubs 文件,stubs 文件只能作为一种之前没写类型信息,后面想补上的补救措施。

请参考《类型提示 - 类型注解.md